<template>
    <el-dialog
        :visible="true"
        width="50%"
        :fullscreen="fullScreen"
        :append-to-body="true"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        :before-close="handleClose">
        <span slot="title" class="el-dialog__title">
            表单脚本
            <el-tooltip effect="dark" content="小程序不支持在线JS脚本" placement="top">
                <i class="el-icon-warning-outline"></i>
            </el-tooltip>
            <i class="el-icon-full-screen iconClass" v-if="!fullScreen" @click="()=>{fullScreen = true}"></i>
            <i class="el-icon-aim iconClass" v-else @click="()=>{fullScreen = false}"></i>
        </span>
        <div class="dialogBody">
            <el-row>
                <el-col :span="6">
                    <div class="leftTree">
                        <el-tree
                            :data="treeList"
                            node-key="label"
                            :props="defaultProps"
                            default-expand-all
                            :expand-on-click-node="false">
                            <span class="custom-tree-node" slot-scope="{ node, data }">
                                <div :class="curClickNodeId === data.$treeNodeId ? 'heightLight textLongCss' : 'textLongCss'" :title="node.label" @click="handleNodeClick(node, data)">{{ node.label }}</div>
                            </span>
                        </el-tree>
                    </div>
                </el-col>
                <el-col :span="18">
                    <div class="rightJs">
                        <codemirror
                            ref="codemirrorRef"
                            v-model="editorValue"
                            id="editorId"
                            :options="cmOptions">
                        </codemirror>
                    </div>
                    <div class="ruleFooter">
                        <div class="ruleText">请从左侧面板选择的字段名，支持JavaScript的脚本，参考编写脚本API</div>
                        <div class="ruleText">data-- 当前组件的选中数据，formData-- 表单数据，setValue-- 设置表单某个组件数据(prop, value)</div>
                        <div class="ruleText">insertAndSetTableData-- 新增子表单数据(tableModel, dataObj)，setValueByTableData-- 更改子表单某列字段的值(tableModel, prop, value)</div>
                        <div class="ruleText">setShowOrHide-- 设置显示或隐藏(prop, value)，setRequired-- 设置必填项(prop, value)</div>
                        <div class="ruleText">setDisabled-- 设置禁用项(prop, value)，request-- 异步请求(url, method, data)</div>
                        <div class="ruleText">getFieldOptions-- 获取表单某个组件的下拉选项值(prop)，setFieldOptions-- 设置某个组件的下拉选项值(prop， options)</div>
                        <div class="ruleText">_this.status-- 判断新增、编辑、查看的状态值</div>
                    </div>
                </el-col>
            </el-row>
            <div class="footerBtn">
                <el-button @click="handleClose">取消</el-button>
                <el-button type="primary" @click="confirm">确定</el-button>
            </div>
        </div>
    </el-dialog>
</template>
<script>
import {deepClone} from '../../../../utils/index.js'
// 全局引入codemirror
import {codemirror} from 'vue-codemirror';
// 引入主题 可以从 codemirror/theme/ 下引入多个
import 'codemirror/theme/mdn-like.css'
import 'codemirror/lib/codemirror.css'
import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/addon/hint/show-hint.js';
import 'codemirror/addon/edit/closebrackets.js';
import 'codemirror/addon/edit/closetag.js';
import 'codemirror/addon/edit/matchbrackets.js';
import 'codemirror/addon/edit/matchtags.js';
import "codemirror/addon/hint/javascript-hint";
import "codemirror/addon/hint/anyword-hint";
// 引入语言模式 可以从 codemirror/mode/ 下引入多个
import 'codemirror/mode/javascript/javascript.js';
export default {
    name: 'FormJS',
    components: {codemirror},
    data () {
        return {
            fullScreen: false,
            treeList: [],
            editorValue: '',
            cmOptions: {
                // 开启自动刷新
	            autorefresh: true,
                // 语言及语法模式
                mode: 'text/javascript',
                // 主题
                theme: 'mdn-like',
                height: 'auto',
                autofocus: true,
                extraKeys: {
                    "Ctrl-/": this.addComment,
                    "Ctrl-d": this.deleteRow
                },
                line: true,
                // 显示行数
                lineNumbers: true,
                // 软换行
                lineWrapping: true,
                // tab宽度
                tabSize: 4,
                matchTags: { bothTags: true },
	            matchBrackets: false, // 在光标点击紧挨{、]括号左、右侧时，自动突出显示匹配的括号 }、]
                autoCloseBrackets: true, // 自动标签闭合
                autoCloseTag: true,
            },
            defaultProps: {
                children: 'children',
                label: 'label'
            },
            curFormParmasLst: [],
            CodeMirror: '',
            editor: '',
            fieldList: [],
            curClickNodeId: -1
        }
    },
    props: ['drawingList', 'curEditorVal', 'newFormName'],
    created () {
        this.treeList.push({ label: this.newFormName,children: [] })
        this.loopGetTree(this.drawingList)
    },
    mounted () {
        const _this = this
        this.$nextTick(() => {
            // 赋予全局变量
            _this.CodeMirror = require("codemirror/lib/codemirror");
            _this.editor = _this.$refs.codemirrorRef.codemirror;

            // 先清空当前mode自带的关键字，再添加自定义关键字(关键字高亮是覆盖了原生样式.cm-s-eclipse span.cm-keyword,样式里有写)
            // _this.CodeMirror.resolveMode("text/javascript").keywords = {}
            // _this.fieldList.forEach(child => {
            //     _this.CodeMirror.resolveMode("text/javascript").keywords[child] = true;
            // })

            _this.editorValue = _this.curEditorVal
        })
    },
    methods: {
        // 快捷键删除行
        deleteRow () {
            if (this.CodeMirror) {
                const selectContent = this.editor.getSelections()
                if (selectContent.length > 1 || (selectContent.length === 1 && selectContent[0] !== '')) {
                    let newList = selectContent.map(content => {return ''})
                    this.editor.replaceSelections(newList, 'select')
                } else {
                    const curSor = this.editor.getCursor();	// 获取当前最新输入
                    const curLine = this.editor.getLine(curSor.line);
                    let newStr = curLine
                    let endCursor = {...curSor}
                    endCursor.ch = newStr.length + 2
                    curSor.ch = 0
                    this.editor.replaceRange('', curSor, endCursor);
                }
            }
        },
        // 快捷键注释
        addComment () {
            if (this.CodeMirror) {
                const selectContent = this.editor.getSelections()
                if (selectContent.length > 1 || (selectContent.length === 1 && selectContent[0] !== '')) {
                    let newList = selectContent.map(content => {return `/*` + content + '*/'})
                    this.editor.replaceSelections(newList, 'select')
                } else {
                    const curSor = this.editor.getCursor();	// 获取当前最新输入
                    const curLine = this.editor.getLine(curSor.line);
                    let newStr = curLine
                    let endCursor = {...curSor}
                    endCursor.ch = newStr.length + 2
                    if (curLine.indexOf('//') !== -1) {
                        newStr = newStr.substring(2, curLine.length)
                        curSor.ch = 0
                        this.editor.replaceRange(newStr, curSor, endCursor);
                    } else {
                        curSor.ch = 0
                        this.editor.replaceRange(`//` + newStr, curSor, endCursor);
                    }
                }
            }
        },
        getSelectedRange() {
	        return {
	            from: this.editor.getCursor(true),
	            to: this.editor.getCursor(false)
	        }
	    },
        // 根据组件层级来生成树形结构
        loopGetTree (list) {
            const _this = this
            let count = 0
            list.forEach(item => {
                if (['Subform', 'el-card', 'el-tabs', 'Steps', 'el-collapse'].includes(item.__config__.tag)) {
                    _this.treeList[0].children.push({
                        label: item.__config__.label,
                        __vModel__: item.__config__.tag === 'Subform' ? item.__vModel__ : '',
                        children: []
                    })
                    if (!['Subform', 'el-card'].includes(item.__config__.tag)) {
                        item.__slot__.options.forEach(newComp => {
                            _this.treeList[0].children[count].children.push({
                                label: ['Steps', 'el-collapse'].includes(item.__config__.tag) ? newComp.title : newComp.label,
                                children: []
                            })
                        })
                    }
                    let insideCount = 0
                    item.__config__.children.forEach(newItem => {
                        newItem.__config__.children.forEach(comp => {
                            if (['Subform', 'el-card'].includes(item.__config__.tag)) {
                                _this.treeList[0].children[count].children.push({
                                    label: comp.__config__.label,
                                    value: comp.__vModel__
                                })
                            }  else {
                                _this.treeList[0].children[count].children[insideCount].children.push({
                                    label: comp.__config__.label,
                                    value: comp.__vModel__
                                })
                            }
                            _this.fieldList.push(comp.__vModel__)
                        })
                        insideCount++
                    })
                    insideCount = 0
                    count++
                } else {
                    _this.treeList[0].children.push({
                        label: item.__config__.label,
                        value: item.__vModel__
                    })
                    _this.fieldList.push(item.__vModel__)
                    count++
                }
            })
        },
        handleNodeClick(node, data) {
            if (data?.children && !data.__vModel__) {
                return
            }
            let position = this.editor.getCursor()
            this.curClickNodeId = data.$treeNodeId
            this.editor.replaceRange(data.__vModel__ ? `${data.__vModel__}` : `${data.value}`, position);
        },
        confirm () {
            this.$emit('confirmJsDialog', this.editorValue)
        },
        // 关闭弹框
        handleClose () {
            this.$emit('closeJsDialog', false)
        },
    }
}
</script>
<style lang="less" scoped>
/deep/.cm-s-mdn-like .cm-string {
    color: lightseagreen;
    font-style: italic;
}
/deep/.cm-s-mdn-like .cm-variable {
    color: deepskyblue;
}
/deep/.el-dialog{
    min-width: 1185px !important;
}
.heightLight{
    background-color: #50bfff;
    color: white;
}
/deep/.el-tree{
    height:690px;
}
/deep/.CodeMirror {
    height: 498px;
}
.ruleText{
    padding: 1px;
    font-weight: 600;
    font-size: 13px;
}
.footerBtn{
    float: right;
    margin-top: 10px;
}
.ruleFooter {
    margin: 10px 0 10px 5px;
    padding: 10px;
    height: 160px;
    background-color: #ecf8ff;
    border: 1px solid #50bfff;
    border-left: 10px solid #50bfff;
}
.leftTree{
    margin: 10px 5px 10px 0;
    height: 690px;
    overflow-y: auto;
    border: 1px solid lightgrey;
}
.rightJs{
    margin: 10px 0 10px 5px;
    height: 520px;
    border: 1px solid lightgrey;
}
.dialogBody{
    padding-top: 10px;
}
/deep/.el-dialog__title{
    width: 100%;
}
.textLongCss{
    max-width:190px;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    height: 25px;
    line-height: 25px;
}
.dialog-footer{
    float: right;
    margin-right: 20px;
}
.iconClass{
    float:right;
    margin-right: 35px;
    line-height: 1.5;
}
/deep/.el-dialog__body{
    height: 780px;
    padding: 0px 20px;
}
::-webkit-scrollbar {
  /*滚动条整体样式*/
  width: 5px; /*高宽分别对应横竖滚动条的尺寸*/
  height: 5px;
}
::-webkit-scrollbar-thumb {
  background-color: #50bfff;
  background-image: -webkit-linear-gradient(
    45deg,
    rgba(255, 255, 255, 0.2) 25%,
    transparent 25%,
    transparent 50%,
    rgba(255, 255, 255, 0.2) 50%,
    rgba(255, 255, 255, 0.2) 75%,
    transparent 75%,
    transparent
  );
  /*滚动条里面小方块*/
  border-radius: 10px;
}
::-webkit-scrollbar-track {
  background: #ededed;
  border-radius: 10px;
  /*滚动条里面轨道*/
  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
}
</style>